//
//  ViewController.m
//  runteraters
//
//  Created by Sebastian Borggrewe on 16/11/2011.
//  Copyright (c) 2011 Robolo. All rights reserved.
//

#import "HunterController.h"
#import "NetworkingCenter.h"
#import "NetworkMessageCreator.h"

@implementation HunterController

@synthesize txtDistance, txtDirection, txtUpdateInterval;
@synthesize imgCompass;
@synthesize catchRunnerBtn;
@synthesize currentTeam = _currentTeam;

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}

- (IBAction)catchRunner:(id)sender {
    // Catch Runner
    [[NetworkingCenter defaultServer] sendMessage:[NetworkMessageCreator catchMessage]];
    
    [((UIButton *)sender) setTitle:@"Catching..." forState:UIControlStateNormal];
    [((UIButton *)sender) setEnabled:NO];
} 

#pragma mark - Location Delegate
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
        
    //NSLog(@"Update frequency: %f, time since last update: %f",updateFrequency,timeSinceLastUpdate);
    
    
    //[txtUpdateInterval setText:[NSString stringWithFormat:@"%f sec",updateFrequency]];
    
    if (goTo != nil)
    [self calculateCurrentDirectionFrom:[newLocation retain] to:goTo];
    
    //NSLog(@"currentDirection: %f",currentDirection);

    if (goTo != nil) 
        [txtDistance setText:[NSString stringWithFormat:@"%f m away", [newLocation distanceFromLocation:goTo]]];
    
    lastLocation = [[CLLocation alloc] initWithLatitude:newLocation.coordinate.latitude longitude:newLocation.coordinate.longitude];
        
    //DLog(@"New Location: %@",newLocation);
    //DLog(@"Current Heading: %f",[newLocation course]);
    
    
    
    //currentHeading = [self toRadian:[newLocation course]];
    DLog(@"Current heading: %f - currentDirection:%f", currentHeading, currentDirection);
    
    if (goTo == nil) txtDirection.text = @"Runner has not been assigned Yet...";
    else txtDirection.text = @"Catch the runner!";
    
    if(currentHeading != -1 && currentDirection != -1)
        [self updateArrowView];
    
    [[NetworkingCenter defaultServer] sendMessage:
        [NetworkMessageCreator locationMessageWithLatitude:newLocation.coordinate.latitude 
                                                 longitude:newLocation.coordinate.longitude 
                                                  accuracy:newLocation.horizontalAccuracy]
     ];

}

- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
    currentHeading = [self toRadian:newHeading.trueHeading];
    
    if(currentHeading != -1 && currentDirection != -1)
        [self updateArrowView];
}

/*
 * Show compass calibration
 */
- (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager {
    //return YES;
    return NO;
}

- (void) updateArrowView {
    //NSLog(@"Update Arrow: %f", currentRotation);
    
    double currentArrowDirection = currentDirection - currentHeading;
    
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    
    [UIView animateWithDuration:0.1f animations:^(void) {
        imgCompass.transform = CGAffineTransformMakeRotation(currentArrowDirection);
    }];
    
    currentRotation = currentArrowDirection;
}

- (void) calculateCurrentDirectionFrom:(CLLocation *)from to:(CLLocation *)to {
    double lat1 = [self toRadian:from.coordinate.latitude];
    double lat2 = [self toRadian:to.coordinate.latitude];
    double dLon = [self toRadian:(to.coordinate.longitude - from.coordinate.longitude)];
    
    double y = sin(dLon) * cos(lat2);
    double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon);
    
    currentDirection = atan2(y, x);
}

#pragma mark - Heading
- (double) toRadian: (double) val
{
    return val * (M_PI / 180);
}

// Convert to degrees from radians
- (double) toDegrees: (double) val
{
    return val * 180 / M_PI;
}

// convert from a radian to a 360 degree format.
- (double) toBearing: (double) val
{
    return ( (int)([self toDegrees: val]) + 360 ) % 360;        // use mod to get the degrees
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    NSLog(@"launched view");
    
	// Do any additional setup after loading the view, typically from a nib.
    
    goTo = nil;
    
    // Init direction and heading variable
    currentHeading = -1;
    currentDirection = -1;
    
    // Init Location Manager
    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    [locationManager startUpdatingLocation];
    [locationManager startUpdatingHeading];
    
    // Initialize the rotation of the compass
    currentRotation = 0;
    
    // Register the controller for receiving network notifications
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(receiveNetworkingNotification:) 
                                                 name:NETWORKING_NOTIFICATION
                                               object:nil];
    
    // Send login message..
    [[NetworkingCenter defaultServer] sendMessage:[NetworkMessageCreator loginMessageWith:@"Sebastian" role:ROLE_HUNTER team:self.currentTeam]];
    
    txtDirection.text = @"Updating Location...";
    
}

/* Processes the network messages according to their
 * id as defined in the NetworkMessage.h
 */
- (void) receiveNetworkingNotification:(NSNotification *) notification
{
    if (![[notification name] isEqualToString:NETWORKING_NOTIFICATION]) return;
    
    // Only if it is a Networking Nofitication
    NSLog(@"Received Notification: %@",[((NetworkMessage*)[notification object]) stringMessage]);
    
    NetworkMessage *message = ((NetworkMessage*)[notification object]);

    // The operator has assigned a new target to the hunter
    if (message.type == kAssignNotifyMessage) {
        
        // Where does the hunter need to go?
        goTo = [[CLLocation alloc] initWithLatitude:[[((NSDictionary *)message.data) objectForKey:@"target_latitude"] doubleValue] longitude:[[((NSDictionary *)message.data) objectForKey:@"target_longitude"] doubleValue]];
        
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"New Target" message:@"The operator has assigned a new Target to you" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        
        [alert show];
        [alert release];
        
        // Calculate compass orientation if you know current location.
        if (lastLocation != nil && goTo != nil) {
            [self calculateCurrentDirectionFrom:lastLocation to:goTo];
        
            if(currentHeading != -1 && currentDirection != -1)
                [self updateArrowView];
        }
        
        
        txtDirection.text = @"Catch the runner!";
    
    
    } else if (message.type == kAllowCatchMessage) {
        // Show catch button
        [catchRunnerBtn setHidden:NO];
    }else if (message.type == kDisallowCatchMessage) {
        
        // Reset interface if you are not allowed to catch the runner anymore
        [catchRunnerBtn setHidden:YES];
        [catchRunnerBtn setEnabled:YES];
        [catchRunnerBtn setTitle:@"Catch enemy runner" forState:UIControlStateNormal];
    }else if (message.type == kCatchEndMessage) {
        
        // Catching successful
        [catchRunnerBtn setHidden:YES];
        [catchRunnerBtn setEnabled:YES];
        [catchRunnerBtn setTitle:@"Catch enemy runner" forState:UIControlStateNormal];
        
        // Runner... caught...
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"WOOOHOOO" message:@"You caught the enemy runner! Good job!" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        
        [alert show];
        [alert release];
    } else if (message.type == kKeyframeRHMessage) {
        
        // Code by Jibin
        NSDictionary *messageData = (NSDictionary *)(message.data);
        double targetLatitude = [[messageData valueForKey:@"target_lat"] doubleValue];
        double targetLongtitude = [[messageData valueForKey:@"target_long"] doubleValue];
        
        if(targetLatitude!=0 && targetLongtitude!=0){
            //You have a target
            goTo = [[CLLocation alloc] initWithLatitude:targetLatitude longitude:targetLongtitude];
            
            if([[messageData valueForKey:@"allowed_to_catch"] boolValue]){
                //You are allowed to catch.
                
                //But the button is still hidden.
                //kAllowCatchMessage is gone.
                if(catchRunnerBtn.hidden == YES) {
                    //Display the button
                    [catchRunnerBtn setHidden:NO];
                    
                }
            } else {
                //You are not allowed to catch.
                
                //But the button is still there.
                //kDisallowCatchMessage is gone.
                if(catchRunnerBtn.hidden == NO) {
                    [catchRunnerBtn setHidden:YES];
                    [catchRunnerBtn setEnabled:YES];
                }
            }
        } else {
            //You don`t have a target.
            
            //After the player press the button
            //kCatchEndMessage is gone.
            if(catchRunnerBtn.hidden == NO && catchRunnerBtn.enabled == NO){
                [catchRunnerBtn setHidden:YES];
                [catchRunnerBtn setEnabled:YES];
                
                // Runner... caught...
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"WOOOHOOO" message:@"You caught the targeted Runner! Good job!" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
                
                [alert show];
                [alert release];
            }
        }
        // Code by Jibin END
    }
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated
{
	[super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated
{
	[super viewDidDisappear:animated];
}

@end
